/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "discovery_command_handler.h"

#include "utils_log.h"
#include "common_product_definition.h"
#include "common_version.h"
#include "common_config_manager.h"
#include "network.h"
#include "utils_task.h"

#include <cctype>

namespace El {
namespace Protocol {

namespace {

// 归一化 MAC 地址：去掉分隔符并转换为小写，方便比较
std::string NormalizeMacAddress(const std::string &mac)
{
    std::string normalized;
    normalized.reserve(mac.size());
    for (char c : mac) {
        if (c == ':' || c == '-' || c == ' ') {
            continue;
        }
        normalized.push_back(static_cast<char>(std::tolower(static_cast<unsigned char>(c))));
    }
    return normalized;
}

} // namespace

void DiscoveryCommandHandler::RegisterMethodHandlers(
    std::unordered_map<std::string, std::function<nlohmann::json(const std::string &, const nlohmann::json &)>>
        &handlers)
{
    handlers["discovery.search"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleDiscoverySearch(id, params);
    };

    handlers["discovery.setIp"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleDiscoverySetIp(id, params);
    };
}

nlohmann::json DiscoveryCommandHandler::HandleDiscoverySearch(const std::string &id, const nlohmann::json &params)
{
    (void)params;
    EL_DEBUG("处理discovery.search请求");

    // 获取设备型号
    std::string model;
    if (!Common::ProductDefinition::GetInstance().GetValue("device_model", model)) {
        EL_ERROR("获取设备型号失败");
        model = "未知设备";
    }

    // 获取固件版本
    std::string version = Common::VersionManager::GetInstance().GetVersionFull();
    if (version.empty()) {
        EL_ERROR("获取固件版本失败");
        version = "未知版本";
    }

    // 获取设备序列号：直接使用eth0的MAC地址（去除冒号）
    std::string serial_number;
    std::string mac = El::Network::Network::GetInstance().GetInterfaceMacAddress("eth0");
    for (char c : mac) {
        if (c != ':') {
            serial_number += c;
        }
    }
    EL_DEBUG("设备序列号(基于MAC地址): {}", serial_number);

    // 获取制造商
    std::string manufacturer;
    if (!Common::ProductDefinition::GetInstance().GetValue("manufacturer", manufacturer)) {
        EL_ERROR("获取制造商信息失败");
        manufacturer = "未知厂商";
    }

    // 获取设备ID
    std::string device_id;
    if (!Common::ProductDefinition::GetInstance().GetValue("device_id", device_id)) {
        EL_ERROR("获取设备ID失败");
        device_id = serial_number; // 使用序列号作为备用
    }

    // 获取网络配置
    auto &configManager = Common::ConfigManager::GetInstance();
    auto networkConfig = configManager.GetConfig("/network");

    auto &network = El::Network::Network::GetInstance();
    nlohmann::json ifStatus;
    network.GetInterfaceStatus("eth0", ifStatus);

    std::string ipAddress = network.GetInterfaceIpAddress("eth0");

    // 获取网关信息
    std::string gateway = "192.168.1.1"; // 默认网关
    if (networkConfig.contains("interfaces") && networkConfig["interfaces"].contains("eth0") &&
        networkConfig["interfaces"]["eth0"].contains("ipv4") &&
        networkConfig["interfaces"]["eth0"]["ipv4"].contains("gateway")) {
        gateway = networkConfig["interfaces"]["eth0"]["ipv4"]["gateway"].get<std::string>();
    }

    // 获取子网掩码信息
    std::string netmask = "255.255.255.0"; // 默认子网掩码
    if (networkConfig.contains("interfaces") && networkConfig["interfaces"].contains("eth0") &&
        networkConfig["interfaces"]["eth0"].contains("ipv4") &&
        networkConfig["interfaces"]["eth0"]["ipv4"].contains("netmask")) {
        netmask = networkConfig["interfaces"]["eth0"]["ipv4"]["netmask"].get<std::string>();
    }

    // 获取真实的MAC地址
    std::string macAddress = network.GetInterfaceMacAddress("eth0");

    // 创建网络信息对象
    nlohmann::json networkInfo = {
        {"mac", macAddress},
        {"ip", ipAddress},
        {"subnet_mask", netmask},
        {"gateway", gateway},
    };

    // 创建响应结果
    nlohmann::json result = {{"device_id", device_id},
                             {"model", model},
                             {"serial_number", serial_number},
                             {"firmware_version", version},
                             {"manufacturer", manufacturer},
                             {"network", networkInfo}};

    return CreateSuccessResponse(id, result);
}

nlohmann::json DiscoveryCommandHandler::HandleDiscoverySetIp(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理discovery.setIp请求, 参数: {}", params.dump());

    // 校验目标MAC参数
    if (!params.contains("mac") || !params["mac"].is_string()) {
        return CreateErrorResponse(id, 400, "缺少mac参数或格式不正确");
    }

    std::string targetMac = params["mac"];

    // 接口名称参数，可选，默认eth0
    std::string interfaceName = "eth0";
    if (params.contains("interface_name") && params["interface_name"].is_string()) {
        interfaceName = params["interface_name"].get<std::string>();
    }

    auto &network = El::Network::Network::GetInstance();
    std::string localMac = network.GetInterfaceMacAddress(interfaceName);

    std::string normalizedTarget = NormalizeMacAddress(targetMac);
    std::string normalizedLocal = NormalizeMacAddress(localMac);

    if (normalizedTarget.empty()) {
        return CreateErrorResponse(id, 400, "mac参数为空或格式不正确");
    }

    // MAC 不匹配时直接忽略请求，返回空响应，由上层决定是否回包
    if (normalizedTarget != normalizedLocal) {
        EL_INFO("discovery.setIp请求被忽略, 目标MAC为{}, 本机MAC为{}", targetMac, localMac);
        return nlohmann::json(); // 空响应
    }

    // 配置模式，支持dhcp和static，默认static
    std::string mode = "static";
    if (params.contains("mode") && params["mode"].is_string()) {
        mode = params["mode"].get<std::string>();
    }

    if (mode != "dhcp" && mode != "static") {
        return CreateErrorResponse(id, 400, "mode必须为dhcp或static");
    }

    nlohmann::json ipv4Config;
    if (mode == "static") {
        if (!params.contains("ipv4") || !params["ipv4"].is_object() || !params["ipv4"].contains("address") ||
            !params["ipv4"].contains("netmask") || !params["ipv4"].contains("gateway")) {
            return CreateErrorResponse(
                id, 400, "静态IP模式需要提供ipv4.address、ipv4.netmask和ipv4.gateway参数");
        }
        ipv4Config = params["ipv4"];
    }

    // 异步应用网络配置，避免阻塞当前请求或导致发送响应失败
    Utils::TaskScheduler::GetInstance().PostTask("DiscoverySetIp", [interfaceName, mode, ipv4Config]() {
        auto &networkInner = El::Network::Network::GetInstance();
        bool ok = false;

        if (mode == "dhcp") {
            EL_INFO("通过discovery.setIp将接口{}配置为DHCP模式", interfaceName);
            ok = networkInner.ConfigureNetworkDhcp(interfaceName);
        } else {
            std::string ipAddress = ipv4Config["address"].get<std::string>();
            std::string netmask = ipv4Config["netmask"].get<std::string>();
            std::string gateway = ipv4Config["gateway"].get<std::string>();
            EL_INFO("通过discovery.setIp将接口{}配置为静态IP: {}/{} via {}", interfaceName, ipAddress, netmask, gateway);
            ok = networkInner.ConfigureNetworkStatic(interfaceName, ipAddress, netmask, gateway);
        }

        if (!ok) {
            EL_ERROR("通过discovery.setIp应用网络配置失败, interface={}", interfaceName);
        } else {
            EL_INFO("通过discovery.setIp应用网络配置成功, interface={}", interfaceName);
        }
    });

    nlohmann::json result = {
        {"status", "accepted"},
        {"mode", mode},
        {"interface_name", interfaceName},
        {"device_mac", localMac},
        {"requires_reboot", false},
    };

    return CreateSuccessResponse(id, result);
}

} // namespace Protocol
} // namespace El

